home *** CD-ROM | disk | FTP | other *** search
/ Hardcore Visual Basic 5.0 (2nd Edition) / Hardcore Visual Basic 5.0 - Second Edition (1997)(Microsoft Press).iso / Code / bytes.cls < prev    next >
Text File  |  1997-06-14  |  13KB  |  435 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "GBytes"
  6. Attribute VB_GlobalNameSpace = True
  7. Attribute VB_Creatable = True
  8. Attribute VB_PredeclaredId = False
  9. Attribute VB_Exposed = True
  10. Option Explicit
  11.  
  12. Public Enum EErrorBytes
  13.     eeBaseBytes = 13430     ' Bytes
  14. End Enum
  15.  
  16. Private aPower2(0 To 31) As Long
  17.  
  18. Sub StrToBytes(ab() As Byte, s As String)
  19.     If MUtility.IsArrayEmpty(ab) Then
  20.         ' Assign to empty array
  21.         ab = StrConv(s, vbFromUnicode)
  22.     Else
  23.         Dim cab As Long
  24.         ' Copy to existing array, padding or truncating if necessary
  25.         cab = UBound(ab) - LBound(ab) + 1
  26.         If Len(s) < cab Then s = s & String$(cab - Len(s), 0)
  27.         If UnicodeTypeLib Then
  28.             Dim st As String
  29.             st = StrConv(s, vbFromUnicode)
  30.             CopyMemoryStr ab(LBound(ab)), st, cab
  31.         Else
  32.             CopyMemoryStr ab(LBound(ab)), s, cab
  33.         End If
  34.     End If
  35. End Sub
  36.  
  37. Function StrToBytesV(s As String) As Variant
  38.     ' Copy to array
  39.     StrToBytesV = StrConv(s, vbFromUnicode)
  40. End Function
  41.  
  42. Function BytesToStr(ab() As Byte) As String
  43.     BytesToStr = StrConv(ab, vbUnicode)
  44. End Function
  45.  
  46. Function ByteZToStr(ab() As Byte) As String
  47.     If UnicodeTypeLib Then
  48.         ByteZToStr = ab
  49.     Else
  50.         ByteZToStr = StrConv(ab, vbUnicode)
  51.     End If
  52.     ByteZToStr = Left$(ByteZToStr, lstrlen(ByteZToStr))
  53. End Function
  54.  
  55. Function BytesToWord(abBuf() As Byte, iOffset As Long) As Integer
  56.     BugAssert iOffset <= UBound(abBuf) + 1 - 2
  57.     Dim w As Integer
  58.     CopyMemory w, abBuf(iOffset), 2
  59.     BytesToWord = w
  60. End Function
  61.  
  62. Function BytesToDWord(abBuf() As Byte, iOffset As Long) As Long
  63.     BugAssert iOffset <= UBound(abBuf) + 1 - 4
  64.     Dim dw As Long
  65.     CopyMemory dw, abBuf(iOffset), 4
  66.     BytesToDWord = dw
  67. End Function
  68.  
  69. Sub BytesFromWord(w As Integer, abBuf() As Byte, iOffset As Long)
  70.     BugAssert iOffset <= UBound(abBuf)
  71.     CopyMemory abBuf(iOffset), w, 2
  72. End Sub
  73.  
  74. ' Read string with length in first byte
  75. Function BytesToPStr(ab() As Byte, iOffset As Long) As String
  76.     BugAssert iOffset <= UBound(ab)
  77.     BytesToPStr = MidBytes(ab, iOffset + 1, ab(iOffset))
  78. End Function
  79.  
  80. Sub BytesFromDWord(dw As Long, abBuf() As Byte, iOffset As Long)
  81.     BugAssert iOffset <= UBound(abBuf) + 1 - 4
  82.     CopyMemory abBuf(iOffset), dw, 4
  83. End Sub
  84.  
  85. '' Emulate relevant Basic string functions for arrays of bytes:
  86. ''     Len$             LenBytes
  87. ''     Mid$ function    MidBytes
  88. ''     Mid$ statement   InsBytes sub
  89. ''     Left$            LeftBytes
  90. ''     Right$           RightBytes
  91.  
  92. ' LenBytes - Emulates Len for array of bytes
  93. Function LenBytes(ab() As Byte) As Long
  94.     LenBytes = UBound(ab) - LBound(ab) + 1
  95. End Function
  96.  
  97. ' MidBytes - emulates Mid$ function for array of bytes
  98. ' (Note that MidBytes does not emulate Mid$ exactly--string fields
  99. ' in byte arrays are often null-padded, and MidBytes can extract
  100. ' non-null portion)
  101. Function MidBytes(ab() As Byte, ByVal iOffset As Long, _
  102.                   Optional ByVal iLen As Long = 0, _
  103.                   Optional fToNull As Boolean = False) As String
  104.     BugAssert iOffset < LenBytes(ab) And iOffset >= 0
  105.     Dim s As String, cab As Long
  106.     ' Calculate length
  107.     If iLen <= 0 Then
  108.         cab = LenBytes(ab) - iOffset
  109.     Else
  110.         cab = iLen
  111.     End If
  112.     ' Assign and return string
  113.     s = String$(cab, 0)
  114.     CopyMemoryToStr s, ab(iOffset), cab
  115.     If UnicodeTypeLib Then s = MUtility.StrZToStr(StrConv(s, vbUnicode))
  116.     If fToNull Then
  117.         cab = InStr(s, vbNullChar)
  118.         If cab Then
  119.             MidBytes = Left$(s, cab - 1)
  120.         Else
  121.             MidBytes = s
  122.         End If
  123.     Else
  124.         MidBytes = s
  125.     End If
  126. End Function
  127.  
  128. ' InsBytes - Emulates Mid$ statement for array of bytes
  129. ' (Note that InsBytes does not emulate Mid$ exactly--it inserts
  130. ' a null-padded string into a fixed-size field in order to work
  131. ' better with common use of byte arrays.)
  132. Sub InsBytes(sIns As String, ab() As Byte, ByVal iOffset As Long, _
  133.              Optional iLen As Long = 0)
  134.     BugAssert iOffset < LenBytes(ab) And iOffset >= 0
  135.     Dim cab As Long
  136.     ' Calculate length
  137.     If iLen <= 0 Then
  138.         cab = Len(sIns)
  139.     Else
  140.         cab = iLen
  141.         ' Null-pad insertion string if too short
  142.         If (Len(sIns) < cab) Then
  143.             sIns = sIns & String$(cab - Len(sIns), 0)
  144.         End If
  145.     End If
  146.     BugAssert (Len(sIns) <= (LenBytes(ab) - iOffset))
  147.     ' Insert string
  148.     If UnicodeTypeLib Then
  149.         Dim s As String
  150.         s = StrConv(sIns, vbFromUnicode)
  151.         CopyMemoryStr ab(iOffset), s, cab
  152.     Else
  153.         CopyMemoryStr ab(iOffset), sIns, cab
  154.     End If
  155. End Sub
  156.  
  157. ' LeftBytes - Emulates Left$ function for array of bytes
  158. Function LeftBytes(ab() As Byte, ByVal iLen As Long) As String
  159.     Dim s As String
  160.     s = String$(iLen, 0)
  161.     CopyMemoryToStr s, ab(LBound(ab)), iLen
  162.     If UnicodeTypeLib Then s = MUtility.StrZToStr(StrConv(s, vbUnicode))
  163.     LeftBytes = s
  164. End Function
  165.  
  166. ' RightBytes - Emulates Right$ function for array of bytes
  167. Function RightBytes(ab() As Byte, ByVal iLen As Long) As String
  168.     Dim s As String
  169.     s = String$(iLen, 0)
  170.     CopyMemoryToStr s, ab(UBound(ab) - iLen + 1), iLen
  171.     If UnicodeTypeLib Then s = MUtility.StrZToStr(StrConv(s, vbUnicode))
  172.     RightBytes = s
  173. End Function
  174.  
  175. ' FillBytes - Fills field in array of bytes with given byte
  176. Sub FillBytes(ab() As Byte, ByVal b As Byte, _
  177.               ByVal iOffset As Long, ByVal iLen As Long)
  178.     BugAssert (iOffset < LenBytes(ab)) And (iOffset >= 0)
  179.     BugAssert iOffset - 1 + iLen <= LenBytes(ab)
  180.     Dim i As Long
  181.     For i = iOffset To iOffset + iLen - 1
  182.         ab(i) = b
  183.     Next
  184. End Sub
  185.  
  186. ' InStrBytes is not implemented because a simple version would
  187. ' simply be equivalent to InStr(ab(), s). This creates a temporary
  188. ' string for ab() on every call. An efficient version that works
  189. ' directly on arrays of bytes could be written in C.
  190.  
  191. Function LoWord(ByVal dw As Long) As Integer
  192.     If dw And &H8000& Then
  193.         LoWord = dw Or &HFFFF0000
  194.     Else
  195.         LoWord = dw And &HFFFF&
  196.     End If
  197. End Function
  198.  
  199. Function HiWord(ByVal dw As Long) As Integer
  200.     HiWord = (dw And &HFFFF0000) \ 65536
  201. End Function
  202.  
  203. Function LoByte(ByVal w As Integer) As Byte
  204.     LoByte = w And &HFF
  205. End Function
  206.  
  207. Function HiByte(ByVal w As Integer) As Byte
  208.     HiByte = (w And &HFF00&) \ 256
  209. End Function
  210.  
  211. Function MakeWord(ByVal bLo As Byte, ByVal bHi As Byte) As Integer
  212.     'CopyMemory MakeWord, bLo, 1
  213.     'CopyMemory ByVal VarPtr(MakeWord) + 1, bHi, 1
  214.     If bHi And &H80 Then
  215.         MakeWord = ((bHi * 256&) + bLo) Or &HFFFF0000
  216.     Else
  217.         MakeWord = (bHi * 256) + bLo
  218.     End If
  219. End Function
  220.  
  221. Function MakeDWord(ByVal wLo As Integer, ByVal wHi As Integer) As Long
  222.     'CopyMemory MakeDWord, wLo, 2
  223.     'CopyMemory ByVal VarPtr(MakeDWord) + 2, wHi, 2
  224.     MakeDWord = (wHi * 65536) + (wLo And &HFFFF&)
  225. End Function
  226.  
  227. Function LShiftWord(ByVal w As Integer, ByVal c As Integer) As Integer
  228.     BugAssert c >= 0 And c <= 15
  229.     Dim dw As Long
  230.     dw = w * Power2(c)
  231.     If dw And &H8000& Then
  232.         LShiftWord = CInt(dw And &H7FFF&) Or &H8000
  233.     Else
  234.         LShiftWord = dw And &HFFFF&
  235.     End If
  236. End Function
  237.  
  238. Function RShiftWord(ByVal w As Integer, ByVal c As Integer) As Integer
  239.     BugAssert c >= 0 And c <= 15
  240.     Dim dw As Long
  241.     If c = 0 Then
  242.         RShiftWord = w
  243.     Else
  244.         dw = w And &HFFFF&
  245.         dw = dw \ Power2(c)
  246.         RShiftWord = dw And &HFFFF&
  247.     End If
  248. End Function
  249.  
  250. Function LShiftDWord(ByVal dw As Long, ByVal c As Integer) As Long
  251.     BugAssert c >= 0 And c <= 31
  252.     Dim dwT As Long
  253.     On Error GoTo FailLShiftDWord
  254.     dwT = dw * Power2(c)
  255.     If dwT And &H80000000 Then
  256.         LShiftDWord = CLng(dwT And &H7FFFFFFF) Or &H80000000
  257.     Else
  258.         LShiftDWord = dwT
  259.     End If
  260.     Exit Function
  261. FailLShiftDWord:
  262.     LShiftDWord = &HFFFFFFFF
  263. End Function
  264.  
  265. Function RShiftDWord(ByVal dw As Long, ByVal c As Integer) As Long
  266.     BugAssert c >= 0 And c <= 31
  267.     On Error GoTo FailRShiftDWord
  268.     If c = 0 Then
  269.         RShiftDWord = dw
  270.     Else
  271.         RShiftDWord = dw \ Power2(c)
  272.     End If
  273.     Exit Function
  274. FailRShiftDWord:
  275.     RShiftDWord = 0
  276. End Function
  277.  
  278. ' Set or clear iBitPos bit in iValue according to whether
  279. ' iTest expression is true.
  280. Sub SetBitWord(ByVal iTest As Boolean, iValue As Integer, _
  281.                ByVal iBitPos As Integer)
  282.     BugAssert iBitPos >= 0 And iBitPos <= 15
  283.     If iTest Then
  284.         iValue = LoWord(iValue Or Power2(iBitPos))
  285.     Else
  286.         iValue = LoWord(iValue And Not Power2(iBitPos))
  287.     End If
  288. End Sub
  289.  
  290. Sub SetBitDWord(ByVal iTest As Boolean, iValue As Long, _
  291.                 ByVal iBitPos As Integer)
  292.     BugAssert iBitPos >= 0 And iBitPos <= 31
  293.     If iTest Then
  294.         iValue = iValue Or Power2(iBitPos)
  295.     Else
  296.         iValue = iValue And Not Power2(iBitPos)
  297.     End If
  298. End Sub
  299.  
  300. ' Get state of iBitPos bit in iValue
  301. Function GetBit(ByVal iValue As Long, ByVal iBitPos As Integer) As Boolean
  302.     BugAssert iBitPos >= 0 And iBitPos <= 31
  303.     GetBit = iValue And Power2(iBitPos)
  304. End Function
  305.  
  306. Function SwapWordBytes(ByVal w As Integer) As Integer
  307.     CopyMemory ByVal VarPtr(SwapWordBytes) + 1, w, 1
  308.     CopyMemory SwapWordBytes, ByVal VarPtr(w) + 1, 1
  309. End Function
  310.  
  311. Function SwapDWordWords(ByVal dw As Long) As Long
  312.     CopyMemory ByVal VarPtr(SwapDWordWords) + 2, dw, 2
  313.     CopyMemory SwapDWordWords, ByVal VarPtr(dw) + 2, 2
  314. End Function
  315.  
  316. ' Swap a little endian DWORD to big endian, or vice versa
  317. Function SwapEndian(ByVal dw As Long) As Long
  318.     CopyMemory ByVal VarPtr(SwapEndian) + 3, dw, 1
  319.     CopyMemory ByVal VarPtr(SwapEndian) + 2, ByVal VarPtr(dw) + 1, 1
  320.     CopyMemory ByVal VarPtr(SwapEndian) + 1, ByVal VarPtr(dw) + 2, 1
  321.     CopyMemory SwapEndian, ByVal VarPtr(dw) + 3, 1
  322. End Function
  323.  
  324. Function VBGetLogicalDrives() As String
  325.  
  326.     Dim f32  As Long, i As Integer, s As String
  327.     f32 = GetLogicalDrives()
  328.     For i = 0 To 25
  329.         s = s & IIf(f32 And 1, "+", "-")
  330.         f32 = MBytes.RShiftDWord(f32, 1)
  331.     Next
  332.     VBGetLogicalDrives = s
  333.     
  334. End Function
  335.  
  336. Property Get Power2(ByVal i As Integer) As Long
  337.     BugAssert i >= 0 And i <= 31
  338. #If fComponent = 0 Then
  339.     If aPower2(0) = 0 Then
  340.         aPower2(0) = &H1&
  341.         aPower2(1) = &H2&
  342.         aPower2(2) = &H4&
  343.         aPower2(3) = &H8&
  344.         aPower2(4) = &H10&
  345.         aPower2(5) = &H20&
  346.         aPower2(6) = &H40&
  347.         aPower2(7) = &H80&
  348.         aPower2(8) = &H100&
  349.         aPower2(9) = &H200&
  350.         aPower2(10) = &H400&
  351.         aPower2(11) = &H800&
  352.         aPower2(12) = &H1000&
  353.         aPower2(13) = &H2000&
  354.         aPower2(14) = &H4000&
  355.         aPower2(15) = &H8000&
  356.         aPower2(16) = &H10000
  357.         aPower2(17) = &H20000
  358.         aPower2(18) = &H40000
  359.         aPower2(19) = &H80000
  360.         aPower2(20) = &H100000
  361.         aPower2(21) = &H200000
  362.         aPower2(22) = &H400000
  363.         aPower2(23) = &H800000
  364.         aPower2(24) = &H1000000
  365.         aPower2(25) = &H2000000
  366.         aPower2(26) = &H4000000
  367.         aPower2(27) = &H8000000
  368.         aPower2(28) = &H10000000
  369.         aPower2(29) = &H20000000
  370.         aPower2(30) = &H40000000
  371.         aPower2(31) = &H80000000
  372.     End If
  373. #End If
  374.     Power2 = aPower2(i)
  375. End Property
  376.  
  377. #If fComponent Then
  378. Private Sub Class_Initialize()
  379.     aPower2(0) = &H1&
  380.     aPower2(1) = &H2&
  381.     aPower2(2) = &H4&
  382.     aPower2(3) = &H8&
  383.     aPower2(4) = &H10&
  384.     aPower2(5) = &H20&
  385.     aPower2(6) = &H40&
  386.     aPower2(7) = &H80&
  387.     aPower2(8) = &H100&
  388.     aPower2(9) = &H200&
  389.     aPower2(10) = &H400&
  390.     aPower2(11) = &H800&
  391.     aPower2(12) = &H1000&
  392.     aPower2(13) = &H2000&
  393.     aPower2(14) = &H4000&
  394.     aPower2(15) = &H8000&
  395.     aPower2(16) = &H10000
  396.     aPower2(17) = &H20000
  397.     aPower2(18) = &H40000
  398.     aPower2(19) = &H80000
  399.     aPower2(20) = &H100000
  400.     aPower2(21) = &H200000
  401.     aPower2(22) = &H400000
  402.     aPower2(23) = &H800000
  403.     aPower2(24) = &H1000000
  404.     aPower2(25) = &H2000000
  405.     aPower2(26) = &H4000000
  406.     aPower2(27) = &H8000000
  407.     aPower2(28) = &H10000000
  408.     aPower2(29) = &H20000000
  409.     aPower2(30) = &H40000000
  410.     aPower2(31) = &H80000000
  411. End Sub
  412. #End If
  413. '
  414.  
  415. #If fComponent = 0 Then
  416. Private Sub ErrRaise(e As Long)
  417.     Dim sText As String, sSource As String
  418.     If e > 1000 Then
  419.         sSource = App.ExeName & ".Bytes"
  420.         Select Case e
  421.         Case eeBaseBytes
  422.             BugAssert True
  423.        ' Case ee...
  424.        '     Add additional errors
  425.         End Select
  426.         Err.Raise COMError(e), sSource, sText
  427.     Else
  428.         ' Raise standard Visual Basic error
  429.         sSource = App.ExeName & ".VBError"
  430.         Err.Raise e, sSource
  431.     End If
  432. End Sub
  433. #End If
  434.  
  435.